Add RequestSendType.ROUND_ROBIN for per-request IP round-robin#2202
Add RequestSendType.ROUND_ROBIN for per-request IP round-robin#2202pavel-ptashyts wants to merge 22 commits into
Conversation
Introduce a requestSendType config option (DEFAULT | ROUND_ROBIN) on DefaultAsyncHttpClientConfig. In ROUND_ROBIN mode, when a host resolves to several IPs, requests are spread strictly per request across all of them: - the resolved address list is rotated per host so each request targets the next IP first, keeping the remaining IPs for TCP failover; - connection reuse is pinned per IP via an IP-aware partition key, so pooled HTTP/1.1 connections and multiplexed HTTP/2 connections are kept per IP; - on failover the key is re-pinned to the IP actually connected to, so reuse stays correct; - the maxConnectionsPerHost semaphore stays per host (the permit is taken before the target IP is known). getRequestSendType() is a default interface method returning DEFAULT, so existing AsyncHttpClientConfig implementations keep compiling. DEFAULT mode behavior is unchanged.
|
This is great - this is essentially client-side load balancing, Let me think through. |
|
Good afternoon. I would be very grateful if you could review my PR, and I will gladly try to improve this solution if you find any shortcomings or issues in it. Client-side load balancing is actually something I sometimes critically miss in the client, as solving the load balancing problem outside the client either works unreliably or requires configuring additional load balancers, which increases system complexity. |
|
Agree - We will get this PR merged no worries. :) |
hyperxpro
left a comment
There was a problem hiding this comment.
Round 1 done - good work indeed!
…and update Copyright to 2026
…ygemdev/async-http-client into requests-round-robin-per-host
pavel-ptashyts
left a comment
There was a problem hiding this comment.
@hyperxpro could you review PR again. Thanks in advance
… in case of redirect from HTTP to HTTPS
Add RequestSendType.ROUND_ROBIN for per-request IP round-robin
Motivation
When a host resolves to several IP addresses (e.g. a service behind DNS that returns multiple A/AAAA records or multiple backend instances), AHC today effectively pins
all traffic to a single IP:
only).
So with keep-alive enabled, the first reachable IP receives essentially all requests, and there is no way to spread client load across a multi-IP host's addresses. This
change adds opt-in client-side round-robin so requests are distributed evenly across all of a host's IPs.
What changed
A new config option requestSendType on DefaultAsyncHttpClientConfig:
asyncHttpClient(config().setRequestSendType(RequestSendType.ROUND_ROBIN));
How ROUND_ROBIN works
the list so the connector can still fail over.
rather than per host. HTTP/2 reuse is governed by the same partition key, so the spread works there too.
Backward compatibility — does not change existing behavior
send/poll/connect/pool path is unchanged.
interface keep compiling (source- and binary-compatible).
explicit address, and proxied requests (the proxy host is resolved, not the target).
Testing
defaults / builder round-trip.